import Block
import Receipt
import SDK
import Transaction
import transactionPool
import time
from binascii import b2a_hex, a2b_hex
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

def legth(value): #AES辅助函数
    l = len(value)
    flag = l % 16
    if flag != 0:
        add = 16 - (l % 16)
        value = value + ('\0' * add).encode('utf-8')
    return value

def encryp_str(content, key, mode, iv): #AES编码函数
    cryptor = AES.new(key, mode, iv)
    # 被加密内容需大于密钥长度,且为16倍数
    key_length = len(key)
    content_legth = len(content)
    if content_legth < key_length:
        add = key_length - content_legth
        content = content + ('\0' * add).encode('utf-8')
    elif content_legth > key_length:
        add = 16 - (content_legth % 16)
        content = content + ('\0' * add).encode('utf-8')
    cipher_content = cryptor.encrypt(content)  # 加密
    cipher_content_hex = b2a_hex(cipher_content)
    cipher_content_hex_de = cipher_content_hex.decode()
    return cipher_content_hex_de

def decryp_str(en_content, key, mode, iv):  #AES解码函数
    cryptor = AES.new(key, mode, iv)
    content = a2b_hex(en_content)
    content = cryptor.decrypt(content)
    content = bytes.decode(content).rstrip('\0')
    return content

def packet(): #交易池满就打包为一个区块，并串到Block_list上
    i=0
    block1 = Block.Block()
    while i<pool.max_length: #把交易放入区块
        block1.transactions.append(pool.transaction_list[i])
        i=i+1
    if(len(bklist)==0):#若为一定个区块，父指针为None
        block1.number=0
        bklist.append(block1)
        return
    l = len(bklist)
    block1.number = l
    ptr = Block.hashPtr() #哈希指针
    ptr.hashNumber = hash(bklist[l-1])
    ptr.Block_ptr = bklist[l-1]
    block1.parentHash = ptr
    bklist.append(block1)

def gong_shi(): #共识函数，此处为空
    return
def transaction_implement(): #交易执行函数，此处为空
    return
def receipt_produce(): #生产交易对应的回执，放入区块的回执树中
    return

bklist = [] #区块保存的地方，假设是单链结构，存储模块的一部分
key1 = legth("1324157389756354".encode('utf-8')) #编码加密用的AES的秘钥
vi = legth(str(3).encode('utf-8'))
sdk = SDK.SDK()
pool = transactionPool.transactionPool()

key2 = RSA.generate(2048) #签名用的RSA秘钥
private_key = key2.export_key()
public_key = key2.publickey().export_key()
publicKey = RSA.import_key(public_key)
cipher1 = PKCS1_OAEP.new(publicKey) #私钥，与名称相反
privateKey = RSA.import_key(private_key)
cipher2 = PKCS1_OAEP.new(privateKey)#公钥，与名称相反

while True :
    time.sleep(5)
    while len(pool.transaction_list) != pool.max_length :#池子没满就不断往其中放置交易
        temp = Transaction.transaction()
        sdk.static_transactionproduct(temp)
        sign = encrypted_data = cipher1.encrypt(str(temp.Nounce).encode()) #私钥加密，形成签名
        str_temp = str(temp)
        encode_temp = str_temp.encode('utf-8')
        temp1=encryp_str(encode_temp,key1,AES.MODE_CBC,vi) #交易编码
        temp2=decryp_str(temp1,key1,AES.MODE_CBC,vi) #交易解码
        de_sign = cipher2.decrypt(sign) #公钥解码
        if(de_sign != str(temp.Nounce).encode()): #如果签名检查错误，不录入交易池
            continue
        pool.add_into_pool(temp)

    packet() #打包放入区块链中
    transaction_implement() #执行刚刚加入区块链的区块的交易
    gong_shi() #对区块进行共识
    receipt_produce()  # 生产交易对应的回执，放入区块的回执树中
    block_to_show = bklist[len(bklist)-1]
    if(block_to_show.parentHash == None):
        print('区块' + str(len(bklist) - 1) + ' 父哈希：' + str(block_to_show.parentHash) + ' 此区块哈希 ' +
              str(hash(block_to_show))  + ' 交易列表(Nounce)：' + str(block_to_show.transactions[0].Nounce)
              +' '+ str(block_to_show.transactions[1].Nounce) +' '+ str(block_to_show.transactions[2].Nounce) +
              ' '+str(block_to_show.transactions[3].Nounce))  # 打印块高，父哈希，此区块哈希，交易列表的信息
        continue

    print('区块'+str(len(bklist)-1)+' 父哈希：'+str(block_to_show.parentHash.hashNumber)+' 此区块哈希 '+
          str(hash(block_to_show)) + ' 交易列表(Nounce)：'+str(block_to_show.transactions[0].Nounce)
          +' '+str(block_to_show.transactions[1].Nounce)+' '+str(block_to_show.transactions[2].Nounce)+' '+
          str(block_to_show.transactions[3].Nounce)) #打印块高，父哈希，此区块哈希，交易列表的信息






